using UnityEngine;
using System.Collections;
using System.Collections.Generic;



namespace BF
{

    public enum AudioPlayType : byte
    {
        /// <summary>
        /// 每个音效之间没任何关系，只要Play就会成功
        /// 即同一时刻可能存在多个播放
        /// </summary>
        Normal = 1,
        /// <summary>
        /// 同一时刻只有一个，继续播放原先的音效
        /// </summary>
        Single = 2,
        /// <summary>
        /// 同一时刻只有一个，停掉上一个，播新的
        /// </summary>
        SingleRestart = 3,
    }

    public class AudioManager
    {
        private static Transform audioCellRoot;
        /// <summary>
        /// 存储已加载音效文件，避免每次都去加载
        /// </summary>
        private static readonly Dictionary<string, AudioClip> _audioClipDic = new Dictionary<string, AudioClip>();
        /// <summary>
        /// 储存正在播音效
        /// </summary>
        private static readonly Dictionary<int, AudioSourceCell> _audioCellDic = new Dictionary<int, AudioSourceCell>();
        /// <summary>
        /// 保存Single类型的正在播放的AudioSourceCell的ID
        /// </summary>
        private static readonly Dictionary<string, int> _singleOriDic = new Dictionary<string, int>();
        /// <summary>
        /// 记录播放时间
        /// </summary>
        private static readonly Dictionary<string, float> _playRecordDic = new Dictionary<string, float>();
        /// <summary>
        /// 是否关闭所有音效
        /// </summary>
        public static bool isMuteAudio { get; private set; }
        /// <summary>
        /// 是否关闭所有背景音乐
        /// </summary>
        public static bool isMuteMusic { get; private set; }

        private static AudioListener _listener;

        public static void Init()
        {
            audioCellRoot = new GameObject("AudioCellRoot").transform;
            Object.DontDestroyOnLoad(audioCellRoot.gameObject);

            MonoPool.InitPool<AudioSourceCell>("AudioSourceCell", "Audio").Prepare(2);

            Timer.Pop().Delay(1).Action(() =>
            {
                _listener = GameObject.FindObjectOfType<AudioListener>();
                if (_listener == null)
                {
                    _listener = audioCellRoot.gameObject.AddComponent<AudioListener>();
                }
                audioCellRoot.transform.position = _listener.transform.position;
            }).Execute();
        }

        /// <summary>
        /// 暂停所有声音
        /// </summary>
        public static void PauseOrResumeAll(bool isPause)
        {
            _listener.enabled = !isPause;
        }

        public static AudioSourceCell PopAudioCell(string audioName)
        {
            audioName = "Audio/" + audioName;
            AudioSourceCell cell = MonoPool.Pop<AudioSourceCell>("AudioSourceCell");
            AudioClip clip = LoadAudioClip(audioName);
            cell.transform.SetParent(audioCellRoot);
            cell.SetClip(clip);
            cell.SetClipName(audioName);
            cell.SendAction(CanPlay, OnRecordPlay, OnRecyle);
            cell.gameObject.SetActive(true);
            return cell;
        }

        /// <summary>
        /// 是否关闭所有音效
        /// </summary>
        public static void SetMuteAudio(bool mute)
        {
            isMuteAudio = mute;
            RefreshAllAudioOnOff();
        }

        /// <summary>
        /// 是否关闭所有背景音乐
        /// </summary>
        public static void SetMuteMusic(bool mute)
        {
            isMuteMusic = mute;
            RefreshAllAudioOnOff();
        }

        /// <summary>
        /// 刷新所有音乐音效开关状态
        /// </summary>
        public static void RefreshAllAudioOnOff()
        {
            foreach (var item in _audioCellDic)
            {
                item.Value.RefreshAudioOnOff();
            }
        }

        /// <summary>
        /// 释放所有已加载的音效文件
        /// </summary>
        public static void UnloadAllAudioClip()
        {
            foreach (var item in _audioClipDic)
            {
                Resources.UnloadAsset(item.Value);
            }
            _audioClipDic.Clear();
        }

        /// <summary>
        /// 释放所有已加载的音效文件
        /// </summary>
        public static IEnumerator AsyncUnloadAllAudioClip()
        {
            List<string> keys = new List<string>(_audioClipDic.Keys);
            foreach (string key in keys)
            {
                if (!_audioClipDic.ContainsKey(key))
                {
                    continue;
                }
                Resources.UnloadAsset(_audioClipDic[key]);
                _audioClipDic.Remove(key);
                yield return null;
            }
        }


        private static bool CanPlay(AudioSourceCell cell)
        {
            //首先判断音效是否有播过，没播过则True
            if (!_playRecordDic.ContainsKey(cell.clipName))
            {
                return true;
            }

            //如果两次播放间隔<该音效的间隔interval则True
            if (cell.interval > 0)
            {
                float record = _playRecordDic[cell.clipName];
                if (Time.time - record <= cell.interval)
                {
                    return false;
                }
            }

            if (cell.audioPlayType == AudioPlayType.Normal)
            {
                return true;
            }

            //(如果是Single的话则需判断当前是否有正在播的，没有正在播放的则True)
            if (!_singleOriDic.ContainsKey(cell.clipName))
            {
                return true;
            }

            if (cell.audioPlayType == AudioPlayType.SingleRestart)
            {
                _audioCellDic[_singleOriDic[cell.clipName]].Stop();
                return true;
            }
            return false;
        }

        private static void OnRecordPlay(AudioSourceCell cell)
        {
            if (!_audioCellDic.ContainsKey(cell.id))
            {
                _audioCellDic.Add(cell.id, cell);
            }

            if (cell.audioPlayType == AudioPlayType.Single)
            {
                _singleOriDic.Add(cell.clipName, cell.id);
            }

            if (_playRecordDic.ContainsKey(cell.clipName))
            {
                _playRecordDic[cell.clipName] = Time.time;
            }
            else
            {
                _playRecordDic.Add(cell.clipName, Time.time);
            }
        }

        private static void OnRecyle(AudioSourceCell cell)
        {
            if (_audioCellDic.ContainsKey(cell.id))
            {
                _audioCellDic.Remove(cell.id);
            }

            if (cell.audioPlayType == AudioPlayType.Single
                && _singleOriDic.ContainsKey(cell.clipName))
            {
                _singleOriDic.Remove(cell.clipName);
            }
        }

        private static AudioClip LoadAudioClip(string audioName)
        {
            if (!_audioClipDic.ContainsKey(audioName))
            {
                AudioClip ac = Resources.Load<AudioClip>(audioName);
                _audioClipDic.Add(audioName, ac);
            }

            return _audioClipDic[audioName];
        }

        public static void StopBgm()
        {
            List<int> keys = new List<int>(_audioCellDic.Keys);
            foreach (int key in keys)
            {
                if (_audioCellDic.ContainsKey(key) && _audioCellDic[key].isBGM)
                {
                    _audioCellDic[key].Stop();
                }
            }
        }

        public static void PlayBgm()
        {
            List<int> keys = new List<int>(_audioCellDic.Keys);
            foreach (int key in keys)
            {
                if (_audioCellDic.ContainsKey(key) && _audioCellDic[key].isBGM)
                {
                    _audioCellDic[key].audioSource.Play();
                }
            }
        }

        public static void PauseBgm()
        {
            List<int> keys = new List<int>(_audioCellDic.Keys);
            foreach (int key in keys)
            {
                if (_audioCellDic.ContainsKey(key) && _audioCellDic[key].isBGM)
                {
                    _audioCellDic[key].audioSource.Pause();
                }
            }
        }

        public static void ResumeBgm()
        {
            List<int> keys = new List<int>(_audioCellDic.Keys);
            foreach (int key in keys)
            {
                if (_audioCellDic.ContainsKey(key) && _audioCellDic[key].isBGM)
                {
                    _audioCellDic[key].audioSource.UnPause();
                }
            }
        }

        public static void Stop(string audioName)
        {
            if (string.IsNullOrEmpty(audioName))
            {
                return;
            }
            List<int> keys = new List<int>(_audioCellDic.Keys);
            foreach (int key in keys)
            {
                if (_audioCellDic.ContainsKey(key) && _audioCellDic[key].clipName.Equals(audioName))
                {
                    _audioCellDic[key].Stop();
                }
            }
        }
    }
}
